home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / imagelib.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  23.9 KB  |  1,144 lines

  1. // imagelib.c
  2.  
  3. #include "cmdlib.h"
  4. #include "imagelib.h"
  5.  
  6.  
  7. int fgetLittleShort (FILE *f)
  8. {
  9.     byte    b1, b2;
  10.  
  11.     b1 = fgetc(f);
  12.     b2 = fgetc(f);
  13.  
  14.     return (short)(b1 + b2*256);
  15. }
  16.  
  17. int fgetLittleLong (FILE *f)
  18. {
  19.     byte    b1, b2, b3, b4;
  20.  
  21.     b1 = fgetc(f);
  22.     b2 = fgetc(f);
  23.     b3 = fgetc(f);
  24.     b4 = fgetc(f);
  25.  
  26.     return b1 + (b2<<8) + (b3<<16) + (b4<<24);
  27. }
  28.  
  29.  
  30.  
  31. /*
  32. ============================================================================
  33.  
  34.                         LBM STUFF
  35.  
  36. ============================================================================
  37. */
  38.  
  39.  
  40. typedef unsigned char    UBYTE;
  41. //conflicts with windows typedef short            WORD;
  42. typedef unsigned short    UWORD;
  43. typedef long            LONG;
  44.  
  45. typedef enum
  46. {
  47.     ms_none,
  48.     ms_mask,
  49.     ms_transcolor,
  50.     ms_lasso
  51. } mask_t;
  52.  
  53. typedef enum
  54. {
  55.     cm_none,
  56.     cm_rle1
  57. } compress_t;
  58.  
  59. typedef struct
  60. {
  61.     UWORD        w,h;
  62.     short        x,y;
  63.     UBYTE        nPlanes;
  64.     UBYTE        masking;
  65.     UBYTE        compression;
  66.     UBYTE        pad1;
  67.     UWORD        transparentColor;
  68.     UBYTE        xAspect,yAspect;
  69.     short        pageWidth,pageHeight;
  70. } bmhd_t;
  71.  
  72. extern    bmhd_t    bmhd;                        // will be in native byte order
  73.  
  74.  
  75.  
  76. #define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
  77. #define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
  78. #define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
  79. #define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
  80. #define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
  81. #define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
  82.  
  83.  
  84. bmhd_t  bmhd;
  85.  
  86. int    Align (int l)
  87. {
  88.     if (l&1)
  89.         return l+1;
  90.     return l;
  91. }
  92.  
  93.  
  94.  
  95. /*
  96. ================
  97. LBMRLEdecompress
  98.  
  99. Source must be evenly aligned!
  100. ================
  101. */
  102. byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
  103. {
  104.     int     count;
  105.     byte    b,rept;
  106.  
  107.     count = 0;
  108.  
  109.     do
  110.     {
  111.         rept = *source++;
  112.  
  113.         if (rept > 0x80)
  114.         {
  115.             rept = (rept^0xff)+2;
  116.             b = *source++;
  117.             memset(unpacked,b,rept);
  118.             unpacked += rept;
  119.         }
  120.         else if (rept < 0x80)
  121.         {
  122.             rept++;
  123.             memcpy(unpacked,source,rept);
  124.             unpacked += rept;
  125.             source += rept;
  126.         }
  127.         else
  128.             rept = 0;               // rept of 0x80 is NOP
  129.  
  130.         count += rept;
  131.  
  132.     } while (count<bpwidth);
  133.  
  134.     if (count>bpwidth)
  135.         Error ("Decompression exceeded width!\n");
  136.  
  137.  
  138.     return source;
  139. }
  140.  
  141.  
  142. /*
  143. =================
  144. LoadLBM
  145. =================
  146. */
  147. void LoadLBM (const char *filename, byte **picture, byte **palette)
  148. {
  149.     byte    *LBMbuffer, *picbuffer, *cmapbuffer;
  150.     int             y;
  151.     byte    *LBM_P, *LBMEND_P;
  152.     byte    *pic_p;
  153.     byte    *body_p;
  154.  
  155.     int    formtype,formlength;
  156.     int    chunktype,chunklength;
  157.  
  158. // qiet compiler warnings
  159.     picbuffer = NULL;
  160.     cmapbuffer = NULL;
  161.  
  162. //
  163. // load the LBM
  164. //
  165.     LoadFile (filename, (void **)&LBMbuffer);
  166.  
  167. //
  168. // parse the LBM header
  169. //
  170.     LBM_P = LBMbuffer;
  171.     if ( *(int *)LBMbuffer != LittleLong(FORMID) )
  172.        Error ("No FORM ID at start of file!\n");
  173.  
  174.     LBM_P += 4;
  175.     formlength = BigLong( *(int *)LBM_P );
  176.     LBM_P += 4;
  177.     LBMEND_P = LBM_P + Align(formlength);
  178.  
  179.     formtype = LittleLong(*(int *)LBM_P);
  180.  
  181.     if (formtype != ILBMID && formtype != PBMID)
  182.         Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
  183.         ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
  184.  
  185.     LBM_P += 4;
  186.  
  187. //
  188. // parse chunks
  189. //
  190.  
  191.     while (LBM_P < LBMEND_P)
  192.     {
  193.         chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
  194.         LBM_P += 4;
  195.         chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
  196.         LBM_P += 4;
  197.  
  198.         switch ( chunktype )
  199.         {
  200.         case BMHDID:
  201.             memcpy (&bmhd,LBM_P,sizeof(bmhd));
  202.             bmhd.w = BigShort(bmhd.w);
  203.             bmhd.h = BigShort(bmhd.h);
  204.             bmhd.x = BigShort(bmhd.x);
  205.             bmhd.y = BigShort(bmhd.y);
  206.             bmhd.pageWidth = BigShort(bmhd.pageWidth);
  207.             bmhd.pageHeight = BigShort(bmhd.pageHeight);
  208.             break;
  209.  
  210.         case CMAPID:
  211.             cmapbuffer = malloc (768);
  212.             memset (cmapbuffer, 0, 768);
  213.             memcpy (cmapbuffer, LBM_P, chunklength);
  214.             break;
  215.  
  216.         case BODYID:
  217.             body_p = LBM_P;
  218.  
  219.             pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
  220.             if (formtype == PBMID)
  221.             {
  222.             //
  223.             // unpack PBM
  224.             //
  225.                 for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
  226.                 {
  227.                     if (bmhd.compression == cm_rle1)
  228.                         body_p = LBMRLEDecompress ((byte *)body_p
  229.                         , pic_p , bmhd.w);
  230.                     else if (bmhd.compression == cm_none)
  231.                     {
  232.                         memcpy (pic_p,body_p,bmhd.w);
  233.                         body_p += Align(bmhd.w);
  234.                     }
  235.                 }
  236.  
  237.             }
  238.             else
  239.             {
  240.             //
  241.             // unpack ILBM
  242.             //
  243.                 Error ("%s is an interlaced LBM, not packed", filename);
  244.             }
  245.             break;
  246.         }
  247.  
  248.         LBM_P += Align(chunklength);
  249.     }
  250.  
  251.     free (LBMbuffer);
  252.  
  253.     *picture = picbuffer;
  254.  
  255.     if (palette)
  256.         *palette = cmapbuffer;
  257. }
  258.  
  259.  
  260. /*
  261. ============================================================================
  262.  
  263.                             WRITE LBM
  264.  
  265. ============================================================================
  266. */
  267.  
  268. /*
  269. ==============
  270. WriteLBMfile
  271. ==============
  272. */
  273. void WriteLBMfile (const char *filename, byte *data,
  274.                    int width, int height, byte *palette)
  275. {
  276.     byte    *lbm, *lbmptr;
  277.     int    *formlength, *bmhdlength, *cmaplength, *bodylength;
  278.     int    length;
  279.     bmhd_t  basebmhd;
  280.  
  281.     lbm = lbmptr = malloc (width*height+1000);
  282.  
  283. //
  284. // start FORM
  285. //
  286.     *lbmptr++ = 'F';
  287.     *lbmptr++ = 'O';
  288.     *lbmptr++ = 'R';
  289.     *lbmptr++ = 'M';
  290.  
  291.     formlength = (int*)lbmptr;
  292.     lbmptr+=4;                      // leave space for length
  293.  
  294.     *lbmptr++ = 'P';
  295.     *lbmptr++ = 'B';
  296.     *lbmptr++ = 'M';
  297.     *lbmptr++ = ' ';
  298.  
  299. //
  300. // write BMHD
  301. //
  302.     *lbmptr++ = 'B';
  303.     *lbmptr++ = 'M';
  304.     *lbmptr++ = 'H';
  305.     *lbmptr++ = 'D';
  306.  
  307.     bmhdlength = (int *)lbmptr;
  308.     lbmptr+=4;                      // leave space for length
  309.  
  310.     memset (&basebmhd,0,sizeof(basebmhd));
  311.     basebmhd.w = BigShort((short)width);
  312.     basebmhd.h = BigShort((short)height);
  313.     basebmhd.nPlanes = BigShort(8);
  314.     basebmhd.xAspect = BigShort(5);
  315.     basebmhd.yAspect = BigShort(6);
  316.     basebmhd.pageWidth = BigShort((short)width);
  317.     basebmhd.pageHeight = BigShort((short)height);
  318.  
  319.     memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
  320.     lbmptr += sizeof(basebmhd);
  321.  
  322.     length = lbmptr-(byte *)bmhdlength-4;
  323.     *bmhdlength = BigLong(length);
  324.     if (length&1)
  325.         *lbmptr++ = 0;          // pad chunk to even offset
  326.  
  327. //
  328. // write CMAP
  329. //
  330.     *lbmptr++ = 'C';
  331.     *lbmptr++ = 'M';
  332.     *lbmptr++ = 'A';
  333.     *lbmptr++ = 'P';
  334.  
  335.     cmaplength = (int *)lbmptr;
  336.     lbmptr+=4;                      // leave space for length
  337.  
  338.     memcpy (lbmptr,palette,768);
  339.     lbmptr += 768;
  340.  
  341.     length = lbmptr-(byte *)cmaplength-4;
  342.     *cmaplength = BigLong(length);
  343.     if (length&1)
  344.         *lbmptr++ = 0;          // pad chunk to even offset
  345.  
  346. //
  347. // write BODY
  348. //
  349.     *lbmptr++ = 'B';
  350.     *lbmptr++ = 'O';
  351.     *lbmptr++ = 'D';
  352.     *lbmptr++ = 'Y';
  353.  
  354.     bodylength = (int *)lbmptr;
  355.     lbmptr+=4;                      // leave space for length
  356.  
  357.     memcpy (lbmptr,data,width*height);
  358.     lbmptr += width*height;
  359.  
  360.     length = lbmptr-(byte *)bodylength-4;
  361.     *bodylength = BigLong(length);
  362.     if (length&1)
  363.         *lbmptr++ = 0;          // pad chunk to even offset
  364.  
  365. //
  366. // done
  367. //
  368.     length = lbmptr-(byte *)formlength-4;
  369.     *formlength = BigLong(length);
  370.     if (length&1)
  371.         *lbmptr++ = 0;          // pad chunk to even offset
  372.  
  373. //
  374. // write output file
  375. //
  376.     SaveFile (filename, lbm, lbmptr-lbm);
  377.     free (lbm);
  378. }
  379.  
  380.  
  381. /*
  382. ============================================================================
  383.  
  384. LOAD PCX
  385.  
  386. ============================================================================
  387. */
  388.  
  389. typedef struct
  390. {
  391.     char    manufacturer;
  392.     char    version;
  393.     char    encoding;
  394.     char    bits_per_pixel;
  395.     unsigned short    xmin,ymin,xmax,ymax;
  396.     unsigned short    hres,vres;
  397.     unsigned char    palette[48];
  398.     char    reserved;
  399.     char    color_planes;
  400.     unsigned short    bytes_per_line;
  401.     unsigned short    palette_type;
  402.     char    filler[58];
  403.     unsigned char    data;            // unbounded
  404. } pcx_t;
  405.  
  406.  
  407. /*
  408. ==============
  409. LoadPCX
  410. ==============
  411. */
  412. void LoadPCX (const char *filename, byte **pic, byte **palette, int *width, int *height)
  413. {
  414.     byte    *raw;
  415.     pcx_t    *pcx;
  416.     int        x, y;
  417.     int        len;
  418.     int        dataByte, runLength;
  419.     byte    *out, *pix;
  420.  
  421.     //
  422.     // load the file
  423.     //
  424.     len = LoadFile (filename, (void **)&raw);
  425.  
  426.     //
  427.     // parse the PCX file
  428.     //
  429.     pcx = (pcx_t *)raw;
  430.     raw = &pcx->data;
  431.  
  432.     pcx->xmin = LittleShort(pcx->xmin);
  433.     pcx->ymin = LittleShort(pcx->ymin);
  434.     pcx->xmax = LittleShort(pcx->xmax);
  435.     pcx->ymax = LittleShort(pcx->ymax);
  436.     pcx->hres = LittleShort(pcx->hres);
  437.     pcx->vres = LittleShort(pcx->vres);
  438.     pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
  439.     pcx->palette_type = LittleShort(pcx->palette_type);
  440.  
  441.     if (pcx->manufacturer != 0x0a
  442.         || pcx->version != 5
  443.         || pcx->encoding != 1
  444.         || pcx->bits_per_pixel != 8
  445.         || pcx->xmax >= 640
  446.         || pcx->ymax >= 480)
  447.         Error ("Bad pcx file %s", filename);
  448.     
  449.     if (palette)
  450.     {
  451.         *palette = malloc(768);
  452.         memcpy (*palette, (byte *)pcx + len - 768, 768);
  453.     }
  454.  
  455.     if (width)
  456.         *width = pcx->xmax+1;
  457.     if (height)
  458.         *height = pcx->ymax+1;
  459.  
  460.     if (!pic)
  461.         return;
  462.  
  463.     out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
  464.     if (!out)
  465.         Error ("Skin_Cache: couldn't allocate");
  466.  
  467.     *pic = out;
  468.  
  469.     pix = out;
  470.  
  471.     for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
  472.     {
  473.         for (x=0 ; x<=pcx->xmax ; )
  474.         {
  475.             dataByte = *raw++;
  476.  
  477.             if((dataByte & 0xC0) == 0xC0)
  478.             {
  479.                 runLength = dataByte & 0x3F;
  480.                 dataByte = *raw++;
  481.             }
  482.             else
  483.                 runLength = 1;
  484.  
  485.             // FIXME: this shouldn't happen, but it does.  Are we decoding the file wrong?
  486.             // Truncate runLength so we don't overrun the end of the buffer
  487.             if ( ( y == pcx->ymax ) && ( x + runLength > pcx->xmax + 1 ) ) {
  488.                 runLength = pcx->xmax - x + 1;
  489.             }
  490.  
  491.             while(runLength-- > 0)
  492.                 pix[x++] = dataByte;
  493.         }
  494.  
  495.     }
  496.  
  497.     if ( raw - (byte *)pcx > len)
  498.         Error ("PCX file %s was malformed", filename);
  499.  
  500.     free (pcx);
  501. }
  502.  
  503. /* 
  504. ============== 
  505. WritePCXfile 
  506. ============== 
  507. */ 
  508. void WritePCXfile (const char *filename, byte *data, 
  509.                    int width, int height, byte *palette) 
  510. {
  511.     int        i, j, length;
  512.     pcx_t    *pcx;
  513.     byte        *pack;
  514.       
  515.     pcx = malloc (width*height*2+1000);
  516.     memset (pcx, 0, sizeof(*pcx));
  517.  
  518.     pcx->manufacturer = 0x0a;    // PCX id
  519.     pcx->version = 5;            // 256 color
  520.      pcx->encoding = 1;        // uncompressed
  521.     pcx->bits_per_pixel = 8;        // 256 color
  522.     pcx->xmin = 0;
  523.     pcx->ymin = 0;
  524.     pcx->xmax = LittleShort((short)(width-1));
  525.     pcx->ymax = LittleShort((short)(height-1));
  526.     pcx->hres = LittleShort((short)width);
  527.     pcx->vres = LittleShort((short)height);
  528.     pcx->color_planes = 1;        // chunky image
  529.     pcx->bytes_per_line = LittleShort((short)width);
  530.     pcx->palette_type = LittleShort(1);        // not a grey scale
  531.  
  532.     // pack the image
  533.     pack = &pcx->data;
  534.     
  535.     for (i=0 ; i<height ; i++)
  536.     {
  537.         for (j=0 ; j<width ; j++)
  538.         {
  539.             if ( (*data & 0xc0) != 0xc0)
  540.                 *pack++ = *data++;
  541.             else
  542.             {
  543.                 *pack++ = 0xc1;
  544.                 *pack++ = *data++;
  545.             }
  546.         }
  547.     }
  548.             
  549.     // write the palette
  550.     *pack++ = 0x0c;    // palette ID byte
  551.     for (i=0 ; i<768 ; i++)
  552.         *pack++ = *palette++;
  553.         
  554. // write output file 
  555.     length = pack - (byte *)pcx;
  556.     SaveFile (filename, pcx, length);
  557.  
  558.     free (pcx);
  559.  
  560. /*
  561. ============================================================================
  562.  
  563. LOAD BMP
  564.  
  565. ============================================================================
  566. */
  567.  
  568.  
  569. /*
  570.  
  571. // we can't just use these structures, because
  572. // compiler structure alignment will not be portable
  573. // on this unaligned stuff
  574.  
  575. typedef struct tagBITMAPFILEHEADER { // bmfh 
  576.         WORD    bfType;                // BM
  577.         DWORD   bfSize; 
  578.         WORD    bfReserved1; 
  579.         WORD    bfReserved2; 
  580.         DWORD   bfOffBits; 
  581. } BITMAPFILEHEADER; 
  582.  
  583. typedef struct tagBITMAPINFOHEADER{ // bmih 
  584.    DWORD  biSize; 
  585.    LONG   biWidth; 
  586.    LONG   biHeight; 
  587.    WORD   biPlanes; 
  588.    WORD   biBitCount 
  589.    DWORD  biCompression; 
  590.    DWORD  biSizeImage; 
  591.    LONG   biXPelsPerMeter; 
  592.    LONG   biYPelsPerMeter; 
  593.    DWORD  biClrUsed; 
  594.    DWORD  biClrImportant; 
  595. } BITMAPINFOHEADER; 
  596.  
  597. typedef struct tagBITMAPINFO { // bmi 
  598.    BITMAPINFOHEADER bmiHeader; 
  599.    RGBQUAD          bmiColors[1]; 
  600. } BITMAPINFO; 
  601.  
  602. typedef struct tagBITMAPCOREHEADER { // bmch 
  603.         DWORD   bcSize; 
  604.         WORD    bcWidth; 
  605.         WORD    bcHeight; 
  606.         WORD    bcPlanes; 
  607.         WORD    bcBitCount; 
  608. } BITMAPCOREHEADER; 
  609.  
  610. typedef struct _BITMAPCOREINFO {    // bmci 
  611.         BITMAPCOREHEADER  bmciHeader; 
  612.         RGBTRIPLE         bmciColors[1]; 
  613. } BITMAPCOREINFO; 
  614.  
  615. */
  616.  
  617. /*
  618. ==============
  619. LoadBMP
  620. ==============
  621. */
  622. void LoadBMP (const char *filename, byte **pic, byte **palette, int *width, int *height)
  623. {
  624.     byte    *out;
  625.     FILE    *fin;
  626.     int        i;
  627.     int        bfSize; 
  628.     int        bfOffBits; 
  629.     int        structSize;
  630.     int        bcWidth; 
  631.     int     bcHeight; 
  632.     int        bcPlanes; 
  633.     int        bcBitCount; 
  634.     byte    bcPalette[1024];
  635.     qboolean    flipped;
  636.  
  637.     fin = fopen (filename, "rb");
  638.     if (!fin) {
  639.         Error ("Couldn't read %s", filename);
  640.     }
  641.  
  642.     i = fgetLittleShort (fin);
  643.     if (i != 'B' + ('M'<<8) ) {
  644.         Error ("%s is not a bmp file", filename);
  645.     }
  646.  
  647.     bfSize = fgetLittleLong (fin);
  648.     fgetLittleShort(fin);
  649.     fgetLittleShort(fin);
  650.     bfOffBits = fgetLittleLong (fin);
  651.  
  652.     // the size will tell us if it is a
  653.     // bitmapinfo or a bitmapcore
  654.     structSize = fgetLittleLong (fin);
  655.     if (structSize == 40) {
  656.         // bitmapinfo
  657.         bcWidth = fgetLittleLong(fin); 
  658.         bcHeight= fgetLittleLong(fin); 
  659.         bcPlanes = fgetLittleShort(fin); 
  660.         bcBitCount = fgetLittleShort(fin); 
  661.  
  662.         fseek (fin, 24, SEEK_CUR);
  663.  
  664.         if (palette) {
  665.             fread (bcPalette, 1, 1024, fin);
  666.             *palette = malloc(768);
  667.  
  668.             for (i = 0 ; i < 256 ; i++) {
  669.                 (*palette)[i * 3 + 0] = bcPalette[i * 4 + 2];
  670.                 (*palette)[i * 3 + 1] = bcPalette[i * 4 + 1];
  671.                 (*palette)[i * 3 + 2] = bcPalette[i * 4 + 0];
  672.             }
  673.         }
  674.     } else if (structSize == 12) {
  675.         // bitmapcore
  676.         bcWidth = fgetLittleShort(fin); 
  677.         bcHeight= fgetLittleShort(fin); 
  678.         bcPlanes = fgetLittleShort(fin); 
  679.         bcBitCount = fgetLittleShort(fin); 
  680.  
  681.         if (palette) {
  682.             fread (bcPalette, 1, 768, fin);
  683.             *palette = malloc(768);
  684.  
  685.             for (i = 0 ; i < 256 ; i++) {
  686.                 (*palette)[i * 3 + 0] = bcPalette[i * 3 + 2];
  687.                 (*palette)[i * 3 + 1] = bcPalette[i * 3 + 1];
  688.                 (*palette)[i * 3 + 2] = bcPalette[i * 3 + 0];
  689.             }
  690.         }
  691.     } else {
  692.         Error ("%s had strange struct size", filename);
  693.     }
  694.     
  695.     if (bcPlanes != 1) {
  696.         Error ("%s was not a single plane image", filename);
  697.     }
  698.  
  699.     if (bcBitCount != 8) {
  700.         Error ("%s was not an 8 bit image", filename);
  701.     }
  702.  
  703.     if (bcHeight < 0) {
  704.         bcHeight = -bcHeight;
  705.         flipped = qtrue;
  706.     } else {
  707.         flipped = qfalse;
  708.     }
  709.  
  710.     if (width)
  711.         *width = bcWidth;
  712.     if (height)
  713.         *height = bcHeight;
  714.  
  715.     if (!pic) {
  716.         fclose (fin);
  717.         return;
  718.     }
  719.  
  720.     out = malloc ( bcWidth * bcHeight );
  721.     *pic = out;
  722.     fseek (fin, bfOffBits, SEEK_SET);
  723.  
  724.     if (flipped) {
  725.         for (i = 0 ; i < bcHeight ; i++) {
  726.             fread (out + bcWidth * (bcHeight - 1 - i), 1, bcWidth, fin);
  727.         }
  728.     } else {
  729.         fread (out, 1, bcWidth*bcHeight, fin);
  730.     }
  731.  
  732.     fclose (fin);
  733. }
  734.  
  735.  
  736. /*
  737. ============================================================================
  738.  
  739. LOAD IMAGE
  740.  
  741. ============================================================================
  742. */
  743.  
  744. /*
  745. ==============
  746. Load256Image
  747.  
  748. Will load either an lbm or pcx, depending on extension.
  749. Any of the return pointers can be NULL if you don't want them.
  750. ==============
  751. */
  752. void Load256Image (const char *name, byte **pixels, byte **palette,
  753.                    int *width, int *height)
  754. {
  755.     char    ext[128];
  756.  
  757.     ExtractFileExtension (name, ext);
  758.     if (!Q_stricmp (ext, "lbm"))
  759.     {
  760.         LoadLBM (name, pixels, palette);
  761.         if (width)
  762.             *width = bmhd.w;
  763.         if (height)
  764.             *height = bmhd.h;
  765.     }
  766.     else if (!Q_stricmp (ext, "pcx"))
  767.     {
  768.         LoadPCX (name, pixels, palette, width, height);
  769.     }
  770.     else if (!Q_stricmp (ext, "bmp"))
  771.     {
  772.         LoadBMP (name, pixels, palette, width, height);
  773.     }
  774.     else
  775.         Error ("%s doesn't have a known image extension", name);
  776. }
  777.  
  778.  
  779. /*
  780. ==============
  781. Save256Image
  782.  
  783. Will save either an lbm or pcx, depending on extension.
  784. ==============
  785. */
  786. void Save256Image (const char *name, byte *pixels, byte *palette,
  787.                    int width, int height)
  788. {
  789.     char    ext[128];
  790.  
  791.     ExtractFileExtension (name, ext);
  792.     if (!Q_stricmp (ext, "lbm"))
  793.     {
  794.         WriteLBMfile (name, pixels, width, height, palette);
  795.     }
  796.     else if (!Q_stricmp (ext, "pcx"))
  797.     {
  798.         WritePCXfile (name, pixels, width, height, palette);
  799.     }
  800.     else
  801.         Error ("%s doesn't have a known image extension", name);
  802. }
  803.  
  804.  
  805.  
  806.  
  807. /*
  808. ============================================================================
  809.  
  810. TARGA IMAGE
  811.  
  812. ============================================================================
  813. */
  814.  
  815. typedef struct _TargaHeader {
  816.     unsigned char     id_length, colormap_type, image_type;
  817.     unsigned short    colormap_index, colormap_length;
  818.     unsigned char    colormap_size;
  819.     unsigned short    x_origin, y_origin, width, height;
  820.     unsigned char    pixel_size, attributes;
  821. } TargaHeader;
  822.  
  823. /*
  824. =============
  825. LoadTGABuffer
  826. =============
  827. */
  828. void LoadTGABuffer ( byte *buffer, byte **pic, int *width, int *height)
  829. {
  830.     int        columns, rows, numPixels;
  831.     byte    *pixbuf;
  832.     int        row, column;
  833.     byte    *buf_p;
  834.     TargaHeader    targa_header;
  835.     byte        *targa_rgba;
  836.  
  837.     *pic = NULL;
  838.  
  839.     buf_p = buffer;
  840.  
  841.     targa_header.id_length = *buf_p++;
  842.     targa_header.colormap_type = *buf_p++;
  843.     targa_header.image_type = *buf_p++;
  844.     
  845.     targa_header.colormap_index = LittleShort ( *(short *)buf_p );
  846.     buf_p += 2;
  847.     targa_header.colormap_length = LittleShort ( *(short *)buf_p );
  848.     buf_p += 2;
  849.     targa_header.colormap_size = *buf_p++;
  850.     targa_header.x_origin = LittleShort ( *(short *)buf_p );
  851.     buf_p += 2;
  852.     targa_header.y_origin = LittleShort ( *(short *)buf_p );
  853.     buf_p += 2;
  854.     targa_header.width = LittleShort ( *(short *)buf_p );
  855.     buf_p += 2;
  856.     targa_header.height = LittleShort ( *(short *)buf_p );
  857.     buf_p += 2;
  858.     targa_header.pixel_size = *buf_p++;
  859.     targa_header.attributes = *buf_p++;
  860.  
  861.     if (targa_header.image_type!=2 
  862.         && targa_header.image_type!=10
  863.         && targa_header.image_type != 3 ) 
  864.     {
  865.         Error("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
  866.     }
  867.  
  868.     if ( targa_header.colormap_type != 0 )
  869.     {
  870.         Error("LoadTGA: colormaps not supported\n" );
  871.     }
  872.  
  873.     if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
  874.     {
  875.         Error("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
  876.     }
  877.  
  878.     columns = targa_header.width;
  879.     rows = targa_header.height;
  880.     numPixels = columns * rows;
  881.  
  882.     if (width)
  883.         *width = columns;
  884.     if (height)
  885.         *height = rows;
  886.  
  887.     targa_rgba = malloc (numPixels*4);
  888.     *pic = targa_rgba;
  889.  
  890.     if (targa_header.id_length != 0)
  891.         buf_p += targa_header.id_length;  // skip TARGA image comment
  892.     
  893.     if ( targa_header.image_type==2 || targa_header.image_type == 3 )
  894.     { 
  895.         // Uncompressed RGB or gray scale image
  896.         for(row=rows-1; row>=0; row--) 
  897.         {
  898.             pixbuf = targa_rgba + row*columns*4;
  899.             for(column=0; column<columns; column++) 
  900.             {
  901.                 unsigned char red,green,blue,alphabyte;
  902.                 switch (targa_header.pixel_size) 
  903.                 {
  904.                     
  905.                 case 8:
  906.                     blue = *buf_p++;
  907.                     green = blue;
  908.                     red = blue;
  909.                     *pixbuf++ = red;
  910.                     *pixbuf++ = green;
  911.                     *pixbuf++ = blue;
  912.                     *pixbuf++ = 255;
  913.                     break;
  914.  
  915.                 case 24:
  916.                     blue = *buf_p++;
  917.                     green = *buf_p++;
  918.                     red = *buf_p++;
  919.                     *pixbuf++ = red;
  920.                     *pixbuf++ = green;
  921.                     *pixbuf++ = blue;
  922.                     *pixbuf++ = 255;
  923.                     break;
  924.                 case 32:
  925.                     blue = *buf_p++;
  926.                     green = *buf_p++;
  927.                     red = *buf_p++;
  928.                     alphabyte = *buf_p++;
  929.                     *pixbuf++ = red;
  930.                     *pixbuf++ = green;
  931.                     *pixbuf++ = blue;
  932.                     *pixbuf++ = alphabyte;
  933.                     break;
  934.                 default:
  935.                     //Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
  936.                     break;
  937.                 }
  938.             }
  939.         }
  940.     }
  941.     else if (targa_header.image_type==10) {   // Runlength encoded RGB images
  942.         unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
  943.  
  944.         red = 0;
  945.         green = 0;
  946.         blue = 0;
  947.         alphabyte = 0xff;
  948.  
  949.         for(row=rows-1; row>=0; row--) {
  950.             pixbuf = targa_rgba + row*columns*4;
  951.             for(column=0; column<columns; ) {
  952.                 packetHeader= *buf_p++;
  953.                 packetSize = 1 + (packetHeader & 0x7f);
  954.                 if (packetHeader & 0x80) {        // run-length packet
  955.                     switch (targa_header.pixel_size) {
  956.                         case 24:
  957.                                 blue = *buf_p++;
  958.                                 green = *buf_p++;
  959.                                 red = *buf_p++;
  960.                                 alphabyte = 255;
  961.                                 break;
  962.                         case 32:
  963.                                 blue = *buf_p++;
  964.                                 green = *buf_p++;
  965.                                 red = *buf_p++;
  966.                                 alphabyte = *buf_p++;
  967.                                 break;
  968.                         default:
  969.                             //Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
  970.                             break;
  971.                     }
  972.     
  973.                     for(j=0;j<packetSize;j++) {
  974.                         *pixbuf++=red;
  975.                         *pixbuf++=green;
  976.                         *pixbuf++=blue;
  977.                         *pixbuf++=alphabyte;
  978.                         column++;
  979.                         if (column==columns) { // run spans across rows
  980.                             column=0;
  981.                             if (row>0)
  982.                                 row--;
  983.                             else
  984.                                 goto breakOut;
  985.                             pixbuf = targa_rgba + row*columns*4;
  986.                         }
  987.                     }
  988.                 }
  989.                 else {                            // non run-length packet
  990.                     for(j=0;j<packetSize;j++) {
  991.                         switch (targa_header.pixel_size) {
  992.                             case 24:
  993.                                     blue = *buf_p++;
  994.                                     green = *buf_p++;
  995.                                     red = *buf_p++;
  996.                                     *pixbuf++ = red;
  997.                                     *pixbuf++ = green;
  998.                                     *pixbuf++ = blue;
  999.                                     *pixbuf++ = 255;
  1000.                                     break;
  1001.                             case 32:
  1002.                                     blue = *buf_p++;
  1003.                                     green = *buf_p++;
  1004.                                     red = *buf_p++;
  1005.                                     alphabyte = *buf_p++;
  1006.                                     *pixbuf++ = red;
  1007.                                     *pixbuf++ = green;
  1008.                                     *pixbuf++ = blue;
  1009.                                     *pixbuf++ = alphabyte;
  1010.                                     break;
  1011.                             default:
  1012.                                 //Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
  1013.                                 break;
  1014.                         }
  1015.                         column++;
  1016.                         if (column==columns) { // pixel packet run spans across rows
  1017.                             column=0;
  1018.                             if (row>0)
  1019.                                 row--;
  1020.                             else
  1021.                                 goto breakOut;
  1022.                             pixbuf = targa_rgba + row*columns*4;
  1023.                         }                        
  1024.                     }
  1025.                 }
  1026.             }
  1027.             breakOut:;
  1028.         }
  1029.     }
  1030.  
  1031.     //free(buffer);
  1032. }
  1033.  
  1034.  
  1035.  
  1036. /*
  1037. =============
  1038. LoadTGA
  1039. =============
  1040. */
  1041. void LoadTGA (const char *name, byte **pixels, int *width, int *height)
  1042. {
  1043.     byte            *buffer;
  1044.   int nLen;
  1045.     //
  1046.     // load the file
  1047.     //
  1048.     nLen = LoadFile ( ( char * ) name, (void **)&buffer);
  1049.     if (nLen == -1) 
  1050.   {
  1051.         Error ("Couldn't read %s", name);
  1052.   }
  1053.  
  1054.   LoadTGABuffer(buffer, pixels, width, height);
  1055.  
  1056. }
  1057.  
  1058.  
  1059. /*
  1060. ================
  1061. WriteTGA
  1062. ================
  1063. */
  1064. void WriteTGA (const char *filename, byte *data, int width, int height) {
  1065.     byte    *buffer;
  1066.     int        i;
  1067.     int        c;
  1068.     FILE    *f;
  1069.  
  1070.     buffer = malloc(width*height*4 + 18);
  1071.     memset (buffer, 0, 18);
  1072.     buffer[2] = 2;        // uncompressed type
  1073.     buffer[12] = width&255;
  1074.     buffer[13] = width>>8;
  1075.     buffer[14] = height&255;
  1076.     buffer[15] = height>>8;
  1077.     buffer[16] = 32;    // pixel size
  1078.  
  1079.     // swap rgb to bgr
  1080.     c = 18 + width * height * 4;
  1081.     for (i=18 ; i<c ; i+=4)
  1082.     {
  1083.         buffer[i] = data[i-18+2];        // blue
  1084.         buffer[i+1] = data[i-18+1];        // green
  1085.         buffer[i+2] = data[i-18+0];        // red
  1086.         buffer[i+3] = data[i-18+3];        // alpha
  1087.     }
  1088.  
  1089.     f = fopen (filename, "wb");
  1090.     fwrite (buffer, 1, c, f);
  1091.     fclose (f);
  1092.  
  1093.     free (buffer);
  1094. }
  1095.  
  1096. /*
  1097. ============================================================================
  1098.  
  1099. LOAD32BITIMAGE
  1100.  
  1101. ============================================================================
  1102. */
  1103.  
  1104. /*
  1105. ==============
  1106. Load32BitImage
  1107.  
  1108. Any of the return pointers can be NULL if you don't want them.
  1109. ==============
  1110. */
  1111. void Load32BitImage (const char *name, unsigned **pixels,  int *width, int *height)
  1112. {
  1113.     char    ext[128];
  1114.     byte    *palette;
  1115.     byte    *pixels8;
  1116.     byte    *pixels32;
  1117.     int        size;
  1118.     int        i;
  1119.     int        v;
  1120.  
  1121.     ExtractFileExtension (name, ext);
  1122.     if (!Q_stricmp (ext, "tga")) {
  1123.         LoadTGA (name, (byte **)pixels, width, height);
  1124.     } else {
  1125.         Load256Image (name, &pixels8, &palette, width, height);
  1126.         if (!pixels) {
  1127.             return;
  1128.         }
  1129.         size = *width * *height;
  1130.         pixels32 = malloc(size * 4);
  1131.         *pixels = (unsigned *)pixels32;
  1132.         for (i = 0 ; i < size ; i++) {
  1133.             v = pixels8[i];
  1134.             pixels32[i*4 + 0] = palette[ v * 3 + 0 ];
  1135.             pixels32[i*4 + 1] = palette[ v * 3 + 1 ];
  1136.             pixels32[i*4 + 2] = palette[ v * 3 + 2 ];
  1137.             pixels32[i*4 + 3] = 0xff;
  1138.         }
  1139.     }
  1140. }
  1141.  
  1142.  
  1143.